﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel.Design;
using System.Windows.Forms.Design;

namespace InfFront.InfoSources.Base.Design
{
    public partial class BaseDesignerControl : UserControl
    {
        private IDesigner designer;

        public BaseDesignerControl()
        {
            InitializeComponent();

            Disposed += OnDisposed;
        }

        public IDesigner Designer
        {
            get
            {
                return designer;
            }
            set
            {
                if (designer != value)
                {
                    if (ChangeService != null)
                    {
                        ChangeService.ComponentChanged -= OnAComponentChanged;
                        ChangeService.ComponentRename -= OnAComponentRename;
                        ChangeService.ComponentAdded -= OnComponentAdded;
                        ChangeService.ComponentRemoved -= OnComponentRemoved;
                    }
                    designer = value;
                    if (ChangeService != null)
                    {
                        ChangeService.ComponentChanged += OnAComponentChanged;
                        ChangeService.ComponentRename += OnAComponentRename;
                        ChangeService.ComponentAdded += OnComponentAdded;
                        ChangeService.ComponentRemoved += OnComponentRemoved;
                    }
                    Rebuild();
                }
            }
        }

        protected IComponent Component
        {
            get { return (Designer == null) ? null : Designer.Component; }
        }

        protected IServiceProvider ServiceProvider
        {
            get { return (Component == null)? null: Component.Site; }
        }

        protected ServiceType GetService<ServiceType>()
            where ServiceType: class
        {
            var sp = ServiceProvider;
            if (sp != null)
                return sp.GetService(typeof(ServiceType)) as ServiceType;
            return null;
        }

        protected IComponentChangeService ChangeService
        {
            get { return GetService<IComponentChangeService>();  }
        }

        protected IDesignerHost DesignerHost
        {
            get { return GetService<IDesignerHost>();  }
        }

        protected ISelectionService SelectionService
        {
            get { return GetService<ISelectionService>(); }
        }

        protected virtual void Rebuild()
        {
            Enabled = (Designer != null);
        }

        public void SetTrayControl(Control tray)
        {
            splitHorizontal.SuspendLayout();
            splitHorizontal.Panel2Collapsed = false;
            splitHorizontal.Panel2.SuspendLayout();
            tray.Dock = DockStyle.Fill;
            splitHorizontal.Panel2.Controls.Add(tray);
            splitHorizontal.SplitterDistance = splitHorizontal.Height - 75;
            splitHorizontal.Panel2.ResumeLayout();
            splitHorizontal.ResumeLayout();
        }

        protected void SelectComponent(object comp)
        {
            var ss = SelectionService;
            if (ss == null)
                return;
            ss.SetSelectedComponents(new object[] { comp }, SelectionTypes.Replace);
        }

        protected virtual void OnComponentRemoved(object sender, ComponentEventArgs e)
        {
        }

        protected virtual void OnComponentAdded(object sender, ComponentEventArgs e)
        {
        }

        protected virtual void OnAComponentChanged(object sender, ComponentChangedEventArgs e)
        {
        }

        protected virtual void OnAComponentRename(object sender, ComponentRenameEventArgs e)
        {
        }

        internal void OnEnter(object sender, EventArgs e)
        {
            SelectComponent(Component);
        }

        private void OnLeave(object sender, EventArgs e)
        {
            var dh = DesignerHost;
            if (dh != null)
                SelectComponent(dh.RootComponent);
        }

        protected virtual void OnDisposed(object sender, EventArgs args)
        {
            Designer = null;
        }

        protected void InitComponentCreationMenuStrip(ContextMenuStrip strip, Type componentType)
        {
            strip.Tag = componentType;
            strip.Opening += OnComponentCreationMenuStripOpening;
            strip.ItemClicked += OnComponentCreationMenuStripItemClicked;
        }

        private void OnComponentCreationMenuStripOpening(object sender, CancelEventArgs e)
        {
            var strip = (ContextMenuStrip)sender;
            strip.Items.Clear();
            var tdService = GetService<ITypeDiscoveryService>();
            foreach (Type type in tdService.GetTypes((Type)strip.Tag, false))
            {
                if (type.IsAbstract || type.IsGenericType)
                    continue;
                if (type.IsNotPublic && !type.Assembly.Equals(DesignerHost.RootComponent.GetType().Assembly))
                    continue;
                strip.Items.Add(type.FullName).Tag = type;
            }
            e.Cancel = false;
        }

        private void OnComponentCreationMenuStripItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            Type componentType = (Type)e.ClickedItem.Tag;
            DesignerHost.CreateComponent(componentType);
        }
    }
}
